using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ContentOverContainer.Common;
using ContentOverContainer.Common.Converter;
using Roslyn.Compilers.CSharp;

namespace ContentOverContainer.Converter
{
    public static class AddAssignConverter
    {
        /// <summary>
        /// Converts the assign expression. (R-Add1 , R-Add2)
        /// </summary>
        /// <param name="pAssignExpression">The binary (assign) expression.</param>
        /// <param name="pConverterData">The p converter data.</param>
        /// <returns></returns>
        /// <author>
        /// Harald Binkle
        /// </author>
        public static ChangeNodeInfo ConvertAddAssignExpression(BinaryExpressionSyntax pAssignExpression, ConverterContext pConverterData)
        {
            if (pConverterData.MultiplicityInfo.Kind != MultiplicityKind.Any)
                return new ChangeNodeInfo(pAssignExpression);//non any case not defined

            var value = pAssignExpression.Right;
            var member = pAssignExpression.Left;

            List<ParameterPair> parameter;
            var valueIsAnyAnnotated = ExpressionSyntaxConverter.GatherBinaryExpressionInfo(pConverterData, value, member, out parameter);

            //build Add statement
            StatementSyntax invocationAddStatement;
            if (valueIsAnyAnnotated)
                invocationAddStatement = Syntax.ParseStatement(string.Format("{0}.AddRange({1}); " + Environment.NewLine, member.ToString(), value.ToString()));//R-ADD2
            else
                invocationAddStatement = Syntax.ParseStatement(string.Format("if({1}!=null) {0}.Add({1});" + Environment.NewLine, member.ToString(), value.ToString()));//R-Add1
            var returnStatement = Syntax.ParseStatement(String.Format("return {0};", member));
            var methodBody = Syntax.Block(invocationAddStatement, returnStatement);

            TypeSyntax exprType = pConverterData.MultiplicityInfo.Type;

            var composition = MethodComposer.BuildMethod("AddAssign",methodBody, parameter, exprType.ToString());
            var replacement = Syntax.ParseExpression(String.Format("{0} = {1}", member.ToString(), composition.InvocationCall));
            var result = new ChangeNodeInfo(replacement);
            var methodSubstitution = new ChangeNodeMethodSubstitution()
                {
                    Class = pAssignExpression.FirstAncestorOrSelf<ClassDeclarationSyntax>(),
                    MethodDeclaration = composition.MethodDecl
                };
            result.MethodSubstitutionList.Add(methodSubstitution);
            return result;
        }
    }
}
